﻿using HalconDotNet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;

namespace DetectApp.Display
{
    public class PolygonControl : ROIControl
    {
        private readonly Canvas _canvas;

        private readonly List<Shape> _docEllipse = new();

        private Path _CurPath;
        private PathFigure _curPathFigure;
        private int _docDiameter = 0;
        private bool _isMove;
        private bool _isRotate;
        private bool _isSCale1;
        private bool _isSCale2;
        private bool _isSCale3;
        private bool _isSCale4;
        private int _pointId;
        private PolyLineSegment _polyLineSegment;
        private Point _startPoint;
        private double _startTopLeft;
        private double _startTopUp;
        private bool IsDraw;
        private bool IsStartDraw;
        public PolygonControl(Canvas canvas, Color color)
        {
            _canvas = canvas;
            _polyLineSegment = new() { };
            _curPathFigure = new();
            _curPathFigure.Segments.Add(_polyLineSegment);
            PathGeometry pathGeometry1 = new();
            pathGeometry1.Figures.Add(_curPathFigure);
            _CurPath = new()
            {
                Stroke = new SolidColorBrush(color),
                Data = pathGeometry1,

                Fill = new SolidColorBrush(Colors.Red) { Opacity = 0.1 },
                StrokeThickness = 0.1,
            };
            _canvas.MouseLeftButtonDown += CurPath_MouseLeftButtonDown;
            _canvas.MouseMove += Canvas_MouseMove;
            _canvas.MouseRightButtonDown += Canvas_MouseRightButtonDown;
            _CurPath.MouseEnter += (sender, e) =>
            {
                UpdateEllipse(_CurPath, canvas);
            };
            _canvas.Children.Add(_CurPath);
            IsStartDraw = true;
            _canvas.Background = new SolidColorBrush(new Color() { A = 20, R = 255, G = 0, B = 0 });
            ROIChange?.Invoke(this, EventArgs.Empty);
        }

        public PolygonControl(Canvas canvas, ROIParam param)
        {
            _canvas = canvas;
            _polyLineSegment = new() { Points = new PointCollection(param.close_points) };
            _curPathFigure = new() { StartPoint = param.close_start, IsClosed = true };
            _curPathFigure.Segments.Add(_polyLineSegment);
            PathGeometry pathGeometry1 = new();
            pathGeometry1.Figures.Add(_curPathFigure);
            _CurPath = new()
            {
                Stroke = new SolidColorBrush(Colors.Red),
                Data = pathGeometry1,

                Fill = new SolidColorBrush(Colors.Red) { Opacity = 0.1 },
                StrokeThickness = 0.1,
            };
            _CurPath.MouseEnter += (s, e) =>
            {
                UpdateEllipse(_CurPath, _canvas);
            };
            _canvas.MouseLeftButtonDown += CurPath_MouseLeftButtonDown;
            _canvas.MouseMove += Canvas_MouseMove;
            Canvas.SetLeft(_CurPath, param.Left);
            Canvas.SetTop(_CurPath, param.Top);
            _canvas.Children.Add(_CurPath);
            ROIChange?.Invoke(this, EventArgs.Empty);
        }

        public double K { get => _canvas.ActualWidth / 500.0; }
        public override ROIParam GetParam()
        {
            ROIParam param = new() { ROIType = ROIType.多边形 };
            param.close_start = _curPathFigure.StartPoint;
            param.close_points = _polyLineSegment.Points.ToList();
            param.Left = Canvas.GetLeft(_CurPath);
            param.Top = Canvas.GetTop(_CurPath);
            return param;
        }

        public override HRegion? GetRegion()
        {
            HRegion region = new();
            Point startPoint = _CurPath.TranslatePoint(_curPathFigure.StartPoint, _canvas);
            HTuple rows = new HTuple(startPoint.Y);
            HTuple cols = new HTuple(startPoint.X);

            rows = rows.TupleConcat(_polyLineSegment.Points.Select(p => _CurPath.TranslatePoint(p, _canvas).Y).ToArray());
            cols = cols.TupleConcat(_polyLineSegment.Points.Select(p => _CurPath.TranslatePoint(p, _canvas).X).ToArray());
            region.GenRegionPolygonFilled(rows, cols);
            return region;
        }

        public override ROIInfo GetROI()
        {
            return new ROIInfo() { ROIType = ROIType.无 };
        }

        public override void Remove()
        {
            _canvas.Children.Remove(_CurPath);
        }

        private void Canvas_MouseMove(object sender, MouseEventArgs e)
        {
            if (Mouse.LeftButton == MouseButtonState.Released)
            {
                _isMove = false; _isSCale1 = false; _isSCale2 = false; _isSCale3 = false; _isSCale4 = false; _isRotate = false;
            }
            if (!_isSCale1 & !_isSCale2 & !_isSCale3 & !_isSCale4 & !_isMove & !_isRotate)
            {
                bool isClear = true;
                if (_CurPath.IsMouseOver == true) { isClear = false; }
                foreach (var rect in _docEllipse)
                {
                    if (rect.IsMouseOver)
                    {
                        isClear = false;
                        break;
                    }
                }
                if (isClear)
                {
                    _docEllipse.ForEach(e => { _canvas.Children.Remove(e); });
                    _docEllipse.Clear();
                };
            }
            if (_isMove)
            {
                Point curPoint = Mouse.GetPosition(_canvas);
                var rPoint = curPoint - _startPoint;
                Canvas.SetLeft(_CurPath, _startTopLeft + rPoint.X);
                Canvas.SetTop(_CurPath, _startTopUp + rPoint.Y);
                UpdateEllipse(_CurPath, _canvas);
                ROIChange?.Invoke(this, EventArgs.Empty);
            }
            if (Mouse.LeftButton == MouseButtonState.Released)
            {
                _isSCale1 = false; _isMove = false;
            }
            if (_isSCale1)
            {
                if (_pointId == -1)
                {
                    _curPathFigure.StartPoint = Mouse.GetPosition(_CurPath);
                }
                else
                {
                    _polyLineSegment.Points[_pointId] = Mouse.GetPosition(_CurPath);
                }
                UpdateEllipse(_CurPath, _canvas);
                ROIChange?.Invoke(this, EventArgs.Empty);
            }
        }

        private void Canvas_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            IsStartDraw = false; IsDraw = false; _isMove = false;
            _canvas.Background = new SolidColorBrush(Colors.Transparent);
            _curPathFigure.IsClosed = true;
            ROIChange?.Invoke(this, EventArgs.Empty);
        }
        private void CurPath_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (IsDraw) { _polyLineSegment.Points.Add(Mouse.GetPosition(_canvas)); }
            if (IsStartDraw)
            {
                _curPathFigure.StartPoint = Mouse.GetPosition(_canvas);
                Canvas.SetTop(_CurPath, 0);
                Canvas.SetLeft(_CurPath, 0);
                IsDraw = true;
                IsStartDraw = false;
            }
            else if (_CurPath.IsMouseOver && !IsStartDraw && !IsDraw)
            {
                _isMove = true;
                _startPoint = Mouse.GetPosition(_canvas);
                _startTopUp = Canvas.GetTop(_CurPath);
                _startTopLeft = Canvas.GetLeft(_CurPath);
            }
        }
        private void UpdateEllipse(Path path, Canvas canvas)
        {
            //ROIChange?.Invoke(this, EventArgs.Empty);
            _docDiameter = (int)(5 * K);
            Brush fillBrush = new SolidColorBrush(Colors.Blue);
            double opacityK = 1;
            _docEllipse.ForEach(e => { canvas.Children.Remove(e); });
            _docEllipse.Clear();
            Point point;
            Ellipse circle1;
            for (int i = 0; i < _polyLineSegment.Points.Count; i++)
            {
                point = path.TranslatePoint(_polyLineSegment.Points[i], canvas);
                circle1 = new() { Width = _docDiameter, Height = _docDiameter, Fill = fillBrush, Opacity = opacityK };
                Canvas.SetLeft(circle1, point.X - _docDiameter / 2);
                Canvas.SetTop(circle1, point.Y - _docDiameter / 2);
                canvas.Children.Add(circle1);
                _docEllipse.Add(circle1);
                circle1.Tag = i;
                circle1.MouseLeftButtonDown += (o, e) =>
                {
                    _isSCale1 = true;
                    if (o is Ellipse ell) { _pointId = (int)ell.Tag; }
                };
            }
            point = path.TranslatePoint(_curPathFigure.StartPoint, canvas);
            circle1 = new() { Width = _docDiameter, Height = _docDiameter, Fill = fillBrush, Opacity = opacityK };
            Canvas.SetLeft(circle1, point.X - _docDiameter / 2);
            Canvas.SetTop(circle1, point.Y - _docDiameter / 2);
            canvas.Children.Add(circle1);
            _docEllipse.Add(circle1);
            circle1.MouseLeftButtonDown += (o, e) =>
            {
                _isSCale1 = true;
                if (o is Ellipse ell) { _pointId = -1; }
            };
        }
    }
}